home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / qtalk.zip / WEAPONS.QC < prev   
Text File  |  1996-10-02  |  28KB  |  1,304 lines

  1. /*
  2.  
  3. Quake Talk By Simon Francis,
  4. sjfranci@csm.uwe.ac.uk
  5. 1/10/96
  6.  
  7.   Just search for QTalk to find my modifications.
  8.  
  9. */
  10. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  11. void () player_run;
  12. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  13. void(vector org, vector vel, float damage) SpawnBlood;
  14. void() SuperDamageSound;
  15.  
  16.  
  17. // called by worldspawn
  18. void() W_Precache =
  19. {
  20.     precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
  21.     precache_sound ("weapons/rocket1i.wav");        // spike gun
  22.     precache_sound ("weapons/sgun1.wav");
  23.     precache_sound ("weapons/guncock.wav"); // player shotgun
  24.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  25.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  26.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  27.     precache_sound ("weapons/spike2.wav");  // super spikes
  28.     precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
  29.     precache_sound ("weapons/grenade.wav"); // grenade launcher
  30.     precache_sound ("weapons/bounce.wav");          // grenade bounce
  31.     precache_sound ("weapons/shotgn2.wav"); // super shotgun
  32.     precache_sound ("talk/ab1.wav"); // QTalk sounds.
  33.     precache_sound ("talk/ab2.wav"); // Any sounds you
  34.     precache_sound ("talk/lg1.wav"); // want to add have
  35.     precache_sound ("talk/pk1.wav"); // to be included
  36.     precache_sound ("talk/pk2.wav"); // here.
  37.     precache_sound ("talk/lg2.wav");
  38. };
  39.  
  40. float() crandom =
  41. {
  42.     return 2*(random() - 0.5);
  43. };
  44.  
  45. /*
  46. ================
  47. W_FireAxe
  48. ================
  49. */
  50. void() W_FireAxe =
  51. {
  52.     local   vector  source;
  53.     local   vector  org;
  54.  
  55.     source = self.origin + '0 0 16';
  56.     traceline (source, source + v_forward*64, FALSE, self);
  57.     if (trace_fraction == 1.0)
  58.         return;
  59.     
  60.     org = trace_endpos - v_forward*4;
  61.  
  62.     if (trace_ent.takedamage)
  63.     {
  64.         trace_ent.axhitme = 1;
  65.         SpawnBlood (org, '0 0 0', 20);
  66.         T_Damage (trace_ent, self, self, 20);
  67.     }
  68.     else
  69.     {       // hit wall
  70.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  71.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  72.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  73.         WriteCoord (MSG_BROADCAST, org_x);
  74.         WriteCoord (MSG_BROADCAST, org_y);
  75.         WriteCoord (MSG_BROADCAST, org_z);
  76.     }
  77. };
  78.  
  79.  
  80. //============================================================================
  81.  
  82.  
  83. vector() wall_velocity =
  84. {
  85.     local vector    vel;
  86.     
  87.     vel = normalize (self.velocity);
  88.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  89.     vel = vel + 2*trace_plane_normal;
  90.     vel = vel * 200;
  91.     
  92.     return vel;
  93. };
  94.  
  95.  
  96. /*
  97. ================
  98. SpawnMeatSpray
  99. ================
  100. */
  101. void(vector org, vector vel) SpawnMeatSpray =
  102. {
  103.     local   entity missile, mpuff;
  104.     local   vector  org;
  105.  
  106.     missile = spawn ();
  107.     missile.owner = self;
  108.     missile.movetype = MOVETYPE_BOUNCE;
  109.     missile.solid = SOLID_NOT;
  110.  
  111.     makevectors (self.angles);
  112.  
  113.     missile.velocity = vel;
  114.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  115.  
  116.     missile.avelocity = '3000 1000 2000';
  117.     
  118. // set missile duration
  119.     missile.nextthink = time + 1;
  120.     missile.think = SUB_Remove;
  121.  
  122.     setmodel (missile, "progs/zom_gib.mdl");
  123.     setsize (missile, '0 0 0', '0 0 0');            
  124.     setorigin (missile, org);
  125. };
  126.  
  127. /*
  128. ================
  129. SpawnBlood
  130. ================
  131. */
  132. void(vector org, vector vel, float damage) SpawnBlood =
  133. {
  134.     particle (org, vel*0.1, 73, damage*2);
  135. };
  136.  
  137. /*
  138. ================
  139. spawn_touchblood
  140. ================
  141. */
  142. void(float damage) spawn_touchblood =
  143. {
  144.     local vector    vel;
  145.  
  146.     vel = wall_velocity () * 0.2;
  147.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  148. };
  149.  
  150.  
  151. /*
  152. ================
  153. SpawnChunk
  154. ================
  155. */
  156. void(vector org, vector vel) SpawnChunk =
  157. {
  158.     particle (org, vel*0.02, 0, 10);
  159. };
  160.  
  161. /*
  162. ==============================================================================
  163.  
  164. MULTI-DAMAGE
  165.  
  166. Collects multiple small damages into a single damage
  167.  
  168. ==============================================================================
  169. */
  170.  
  171. entity  multi_ent;
  172. float   multi_damage;
  173.  
  174. void() ClearMultiDamage =
  175. {
  176.     multi_ent = world;
  177.     multi_damage = 0;
  178. };
  179.  
  180. void() ApplyMultiDamage =
  181. {
  182.     if (!multi_ent)
  183.         return;
  184.     T_Damage (multi_ent, self, self, multi_damage);
  185. };
  186.  
  187. void(entity hit, float damage) AddMultiDamage =
  188. {
  189.     if (!hit)
  190.         return;
  191.     
  192.     if (hit != multi_ent)
  193.     {
  194.         ApplyMultiDamage ();
  195.         multi_damage = damage;
  196.         multi_ent = hit;
  197.     }
  198.     else
  199.         multi_damage = multi_damage + damage;
  200. };
  201.  
  202. /*
  203. ==============================================================================
  204.  
  205. BULLETS
  206.  
  207. ==============================================================================
  208. */
  209.  
  210. /*
  211. ================
  212. TraceAttack
  213. ================
  214. */
  215. void(float damage, vector dir) TraceAttack =
  216. {
  217.     local   vector  vel, org;
  218.     
  219.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  220.     vel = vel + 2*trace_plane_normal;
  221.     vel = vel * 200;
  222.  
  223.     org = trace_endpos - dir*4;
  224.  
  225.     if (trace_ent.takedamage)
  226.     {
  227.         SpawnBlood (org, vel*0.2, damage);
  228.         AddMultiDamage (trace_ent, damage);
  229.     }
  230.     else
  231.     {
  232.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  233.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  234.         WriteCoord (MSG_BROADCAST, org_x);
  235.         WriteCoord (MSG_BROADCAST, org_y);
  236.         WriteCoord (MSG_BROADCAST, org_z);
  237.     }
  238. };
  239.  
  240. /*
  241. ================
  242. FireBullets
  243.  
  244. Used by shotgun, super shotgun, and enemy soldier firing
  245. Go to the trouble of combining multiple pellets into a single damage call.
  246. ================
  247. */
  248. void(float shotcount, vector dir, vector spread) FireBullets =
  249. {
  250.     local   vector direction;
  251.     local   vector  src;
  252.     
  253.     makevectors(self.v_angle);
  254.  
  255.     src = self.origin + v_forward*10;
  256.     src_z = self.absmin_z + self.size_z * 0.7;
  257.  
  258.     ClearMultiDamage ();
  259.     while (shotcount > 0)
  260.     {
  261.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  262.  
  263.         traceline (src, src + direction*2048, FALSE, self);
  264.         if (trace_fraction != 1.0)
  265.             TraceAttack (4, direction);
  266.  
  267.         shotcount = shotcount - 1;
  268.     }
  269.     ApplyMultiDamage ();
  270. };
  271.  
  272. /*
  273. ================
  274. W_FireShotgun
  275. ================
  276. */
  277. void() W_FireShotgun =
  278. {
  279.     local vector dir;
  280.  
  281.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); 
  282.  
  283.     self.punchangle_x = -2;
  284.     
  285.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  286.     dir = aim (self, 100000);
  287.     FireBullets (6, dir, '0.04 0.04 0');
  288. };
  289.  
  290.  
  291. /*
  292. ================
  293. W_FireSuperShotgun
  294. ================
  295. */
  296. void() W_FireSuperShotgun =
  297. {
  298.     local vector dir;
  299.  
  300.     if (self.currentammo == 1)
  301.     {
  302.         W_FireShotgun ();
  303.         return;
  304.     }
  305.         
  306.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 
  307.  
  308.     self.punchangle_x = -4;
  309.     
  310.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  311.     dir = aim (self, 100000);
  312.     FireBullets (14, dir, '0.14 0.08 0');
  313. };
  314.  
  315.  
  316. /*
  317. ==============================================================================
  318.  
  319. ROCKETS
  320.  
  321. ==============================================================================
  322. */
  323.  
  324. void()  s_explode1      =       [0,             s_explode2] {};
  325. void()  s_explode2      =       [1,             s_explode3] {};
  326. void()  s_explode3      =       [2,             s_explode4] {};
  327. void()  s_explode4      =       [3,             s_explode5] {};
  328. void()  s_explode5      =       [4,             s_explode6] {};
  329. void()  s_explode6      =       [5,             SUB_Remove] {};
  330.  
  331. void() BecomeExplosion =
  332. {
  333.     self.movetype = MOVETYPE_NONE;
  334.     self.velocity = '0 0 0';
  335.     self.touch = SUB_Null;
  336.     setmodel (self, "progs/s_explod.spr");
  337.     self.solid = SOLID_NOT;
  338.     s_explode1 ();
  339. };
  340.  
  341. void() T_MissileTouch =
  342. {
  343.     local float     damg;
  344.  
  345.     if (other == self.owner)
  346.         return;         // don't explode on owner
  347.  
  348.     if (pointcontents(self.origin) == CONTENT_SKY)
  349.     {
  350.         remove(self);
  351.         return;
  352.     }
  353.  
  354.     damg = 100 + random()*20;
  355.     
  356.     if (other.health)
  357.     {
  358.         if (other.classname == "monster_shambler")
  359.             damg = damg * 0.5;      // mostly immune
  360.         T_Damage (other, self, self.owner, damg );
  361.     }
  362.  
  363.     // don't do radius damage to the other, because all the damage
  364.     // was done in the impact
  365.     T_RadiusDamage (self, self.owner, 120, other);
  366.  
  367. //      sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  368.     self.origin = self.origin - 8*normalize(self.velocity);
  369.  
  370.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  371.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  372.     WriteCoord (MSG_BROADCAST, self.origin_x);
  373.     WriteCoord (MSG_BROADCAST, self.origin_y);
  374.     WriteCoord (MSG_BROADCAST, self.origin_z);
  375.  
  376.     BecomeExplosion ();
  377. };
  378.  
  379.  
  380.  
  381. /*
  382. ================
  383. W_FireRocket
  384. ================
  385. */
  386. void() W_FireRocket =
  387. {
  388.     local   entity missile, mpuff;
  389.     
  390.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  391.     
  392.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  393.  
  394.     self.punchangle_x = -2;
  395.  
  396.     missile = spawn ();
  397.     missile.owner = self;
  398.     missile.movetype = MOVETYPE_FLYMISSILE;
  399.     missile.solid = SOLID_BBOX;
  400.         
  401. // set missile speed    
  402.  
  403.     makevectors (self.v_angle);
  404.     missile.velocity = aim(self, 1000);
  405.     missile.velocity = missile.velocity * 1000;
  406.     missile.angles = vectoangles(missile.velocity);
  407.     
  408.     missile.touch = T_MissileTouch;
  409.     
  410. // set missile duration
  411.     missile.nextthink = time + 5;
  412.     missile.think = SUB_Remove;
  413.  
  414.     setmodel (missile, "progs/missile.mdl");
  415.     setsize (missile, '0 0 0', '0 0 0');            
  416.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  417. };
  418.  
  419. /*
  420. ===============================================================================
  421.  
  422. LIGHTNING
  423.  
  424. ===============================================================================
  425. */
  426.  
  427. /*
  428. =================
  429. LightningDamage
  430. =================
  431. */
  432. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  433. {
  434.     local entity            e1, e2;
  435.     local vector            f;
  436.     
  437.     f = p2 - p1;
  438.     normalize (f);
  439.     f_x = 0 - f_y;
  440.     f_y = f_x;
  441.     f_z = 0;
  442.     f = f*16;
  443.  
  444.     e1 = e2 = world;
  445.  
  446.     traceline (p1, p2, FALSE, self);
  447.     if (trace_ent.takedamage)
  448.     {
  449.         particle (trace_endpos, '0 0 100', 225, damage*4);
  450.         T_Damage (trace_ent, from, from, damage);
  451.         if (self.classname == "player")
  452.         {
  453.             if (other.classname == "player")
  454.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  455.         }
  456.     }
  457.     e1 = trace_ent;
  458.  
  459.     traceline (p1 + f, p2 + f, FALSE, self);
  460.     if (trace_ent != e1 && trace_ent.takedamage)
  461.     {
  462.         particle (trace_endpos, '0 0 100', 225, damage*4);
  463.         T_Damage (trace_ent, from, from, damage);
  464.     }
  465.     e2 = trace_ent;
  466.  
  467.     traceline (p1 - f, p2 - f, FALSE, self);
  468.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  469.     {
  470.         particle (trace_endpos, '0 0 100', 225, damage*4);
  471.         T_Damage (trace_ent, from, from, damage);
  472.     }
  473. };
  474.  
  475.  
  476. void() W_FireLightning =
  477. {
  478.     local   vector          org;
  479.  
  480.     if (self.ammo_cells < 1)
  481.     {
  482.         self.weapon = W_BestWeapon ();
  483.         W_SetCurrentAmmo ();
  484.         return;
  485.     }
  486.  
  487. // explode if under water
  488.     if (self.waterlevel > 1)
  489.     {
  490.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  491.         self.ammo_cells = 0;
  492.         W_SetCurrentAmmo ();
  493.         return;
  494.     }
  495.  
  496.     if (self.t_width < time)
  497.     {
  498.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  499.         self.t_width = time + 0.6;
  500.     }
  501.     self.punchangle_x = -2;
  502.  
  503.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  504.  
  505.     org = self.origin + '0 0 16';
  506.     
  507.     traceline (org, org + v_forward*600, TRUE, self);
  508.  
  509.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  510.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  511.     WriteEntity (MSG_BROADCAST, self);
  512.     WriteCoord (MSG_BROADCAST, org_x);
  513.     WriteCoord (MSG_BROADCAST, org_y);
  514.     WriteCoord (MSG_BROADCAST, org_z);
  515.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  516.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  517.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  518.  
  519.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  520. };
  521.  
  522.  
  523. //=============================================================================
  524.  
  525.  
  526. void() GrenadeExplode =
  527. {
  528.     T_RadiusDamage (self, self.owner, 120, world);
  529.  
  530.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  531.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  532.     WriteCoord (MSG_BROADCAST, self.origin_x);
  533.     WriteCoord (MSG_BROADCAST, self.origin_y);
  534.     WriteCoord (MSG_BROADCAST, self.origin_z);
  535.  
  536.     BecomeExplosion ();
  537. };
  538.  
  539. void() GrenadeTouch =
  540. {
  541.     if (other == self.owner)
  542.         return;         // don't explode on owner
  543.     if (other.takedamage == DAMAGE_AIM)
  544.     {
  545.         GrenadeExplode();
  546.         return;
  547.     }
  548.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  549.     if (self.velocity == '0 0 0')
  550.         self.avelocity = '0 0 0';
  551. };
  552.  
  553. /*
  554. ================
  555. W_FireGrenade
  556. ================
  557. */
  558. void() W_FireGrenade =
  559. {
  560.     local   entity missile, mpuff;
  561.     
  562.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  563.     
  564.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  565.  
  566.     self.punchangle_x = -2;
  567.  
  568.     missile = spawn ();
  569.     missile.owner = self;
  570.     missile.movetype = MOVETYPE_BOUNCE;
  571.     missile.solid = SOLID_BBOX;
  572.     missile.classname = "grenade";
  573.         
  574. // set missile speed    
  575.  
  576.     makevectors (self.v_angle);
  577.  
  578.     if (self.v_angle_x)
  579.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  580.     else
  581.     {
  582.         missile.velocity = aim(self, 10000);
  583.         missile.velocity = missile.velocity * 600;
  584.         missile.velocity_z = 200;
  585.     }
  586.  
  587.     missile.avelocity = '300 300 300';
  588.  
  589.     missile.angles = vectoangles(missile.velocity);
  590.     
  591.     missile.touch = GrenadeTouch;
  592.     
  593. // set missile duration
  594.     missile.nextthink = time + 2.5;
  595.     missile.think = GrenadeExplode;
  596.  
  597.     setmodel (missile, "progs/grenade.mdl");
  598.     setsize (missile, '0 0 0', '0 0 0');            
  599.     setorigin (missile, self.origin);
  600. };
  601.  
  602.  
  603. //=============================================================================
  604.  
  605. void() spike_touch;
  606. void() superspike_touch;
  607.  
  608.  
  609. /*
  610. ===============
  611. launch_spike
  612.  
  613. Used for both the player and the ogre
  614. ===============
  615. */
  616. void(vector org, vector dir) launch_spike =
  617. {
  618.     newmis = spawn ();
  619.     newmis.owner = self;
  620.     newmis.movetype = MOVETYPE_FLYMISSILE;
  621.     newmis.solid = SOLID_BBOX;
  622.  
  623.     newmis.angles = vectoangles(dir);
  624.     
  625.     newmis.touch = spike_touch;
  626.     newmis.classname = "spike";
  627.     newmis.think = SUB_Remove;
  628.     newmis.nextthink = time + 6;
  629.     setmodel (newmis, "progs/spike.mdl");
  630.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  631.     setorigin (newmis, org);
  632.  
  633.     newmis.velocity = dir * 1000;
  634. };
  635.  
  636. void() W_FireSuperSpikes =
  637. {
  638.     local vector    dir;
  639.     local entity    old;
  640.     
  641.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  642.     self.attack_finished = time + 0.2;
  643.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  644.     dir = aim (self, 1000);
  645.     launch_spike (self.origin + '0 0 16', dir);
  646.     newmis.touch = superspike_touch;
  647.     setmodel (newmis, "progs/s_spike.mdl");
  648.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  649.     self.punchangle_x = -2;
  650. };
  651.  
  652. void(float ox) W_FireSpikes =
  653. {
  654.     local vector    dir;
  655.     local entity    old;
  656.     
  657.     makevectors (self.v_angle);
  658.     
  659.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  660.     {
  661.         W_FireSuperSpikes ();
  662.         return;
  663.     }
  664.  
  665.     if (self.ammo_nails < 1)
  666.     {
  667.         self.weapon = W_BestWeapon ();
  668.         W_SetCurrentAmmo ();
  669.         return;
  670.     }
  671.  
  672.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  673.     self.attack_finished = time + 0.2;
  674.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  675.     dir = aim (self, 1000);
  676.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  677.  
  678.     self.punchangle_x = -2;
  679. };
  680.  
  681.  
  682.  
  683. .float hit_z;
  684. void() spike_touch =
  685. {
  686. local float rand;
  687.     if (other == self.owner)
  688.         return;
  689.  
  690.     if (other.solid == SOLID_TRIGGER)
  691.         return; // trigger field, do nothing
  692.  
  693.     if (pointcontents(self.origin) == CONTENT_SKY)
  694.     {
  695.         remove(self);
  696.         return;
  697.     }
  698.     
  699. // hit something that bleeds
  700.     if (other.takedamage)
  701.     {
  702.         spawn_touchblood (9);
  703.         T_Damage (other, self, self.owner, 9);
  704.     }
  705.     else
  706.     {
  707.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  708.         
  709.         if (self.classname == "wizspike")
  710.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  711.         else if (self.classname == "knightspike")
  712.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  713.         else
  714.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  715.         WriteCoord (MSG_BROADCAST, self.origin_x);
  716.         WriteCoord (MSG_BROADCAST, self.origin_y);
  717.         WriteCoord (MSG_BROADCAST, self.origin_z);
  718.     }
  719.  
  720.     remove(self);
  721.  
  722. };
  723.  
  724. void() superspike_touch =
  725. {
  726. local float rand;
  727.     if (other == self.owner)
  728.         return;
  729.  
  730.     if (other.solid == SOLID_TRIGGER)
  731.         return; // trigger field, do nothing
  732.  
  733.     if (pointcontents(self.origin) == CONTENT_SKY)
  734.     {
  735.         remove(self);
  736.         return;
  737.     }
  738.     
  739. // hit something that bleeds
  740.     if (other.takedamage)
  741.     {
  742.         spawn_touchblood (18);
  743.         T_Damage (other, self, self.owner, 18);
  744.     }
  745.     else
  746.     {
  747.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  748.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  749.         WriteCoord (MSG_BROADCAST, self.origin_x);
  750.         WriteCoord (MSG_BROADCAST, self.origin_y);
  751.         WriteCoord (MSG_BROADCAST, self.origin_z);
  752.     }
  753.  
  754.     remove(self);
  755.  
  756. };
  757.  
  758. /*
  759. =====================================================================
  760.  
  761. Quake Talk
  762. ==========
  763. If you change the names of the wav files, you have to change the 
  764. precache at the start to match.
  765.  
  766. =====================================================================
  767. */
  768.  
  769. void() play_abuse =
  770. {
  771.     local   float v;
  772.     local   string tmpstr;
  773.  
  774.     v = random() * 2;
  775.     if (v < 1)
  776.         tmpstr = "talk/ab1.wav";
  777.     else
  778.         tmpstr = "talk/ab2.wav";
  779.  
  780.     sound (self, CHAN_AUTO, tmpstr, 1, ATTN_NORM);
  781. };
  782.  
  783.  
  784. void() play_prekill =
  785. {
  786.     local   float v;
  787.     local   string tmpstr;
  788.  
  789.     v = random() * 2;
  790.     if (v < 1)
  791.         tmpstr = "talk/pk1.wav";
  792.     else
  793.         tmpstr = "talk/pk2.wav";
  794.     
  795.     sound (self, CHAN_AUTO, tmpstr, 1, ATTN_NORM);
  796. };
  797.  
  798.  
  799. void() play_letsgo =
  800. {
  801.     local   float v;
  802.     local   string tmpstr;
  803.  
  804.     v = random() * 2;
  805.     if (v < 1)
  806.         tmpstr = "talk/lg1.wav";
  807.     else
  808.         tmpstr = "talk/lg2.wav";
  809.     
  810.     sound (self, CHAN_AUTO, tmpstr, 1, ATTN_NORM);
  811. };
  812.  
  813. // ******************************************************************
  814.  
  815. /*
  816. ===============================================================================
  817.  
  818. PLAYER WEAPON USE
  819.  
  820. ===============================================================================
  821. */
  822.  
  823. void() W_SetCurrentAmmo =
  824. {
  825.     player_run ();          // get out of any weapon firing states
  826.  
  827.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  828.     
  829.     if (self.weapon == IT_AXE)
  830.     {
  831.         self.currentammo = 0;
  832.         self.weaponmodel = "progs/v_axe.mdl";
  833.         self.weaponframe = 0;
  834.     }
  835.     else if (self.weapon == IT_SHOTGUN)
  836.     {
  837.         self.currentammo = self.ammo_shells;
  838.         self.weaponmodel = "progs/v_shot.mdl";
  839.         self.weaponframe = 0;
  840.         self.items = self.items | IT_SHELLS;
  841.     }
  842.     else if (self.weapon == IT_SUPER_SHOTGUN)
  843.     {
  844.         self.currentammo = self.ammo_shells;
  845.         self.weaponmodel = "progs/v_shot2.mdl";
  846.         self.weaponframe = 0;
  847.         self.items = self.items | IT_SHELLS;
  848.     }
  849.     else if (self.weapon == IT_NAILGUN)
  850.     {
  851.         self.currentammo = self.ammo_nails;
  852.         self.weaponmodel = "progs/v_nail.mdl";
  853.         self.weaponframe = 0;
  854.         self.items = self.items | IT_NAILS;
  855.     }
  856.     else if (self.weapon == IT_SUPER_NAILGUN)
  857.     {
  858.         self.currentammo = self.ammo_nails;
  859.         self.weaponmodel = "progs/v_nail2.mdl";
  860.         self.weaponframe = 0;
  861.         self.items = self.items | IT_NAILS;
  862.     }
  863.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  864.     {
  865.         self.currentammo = self.ammo_rockets;
  866.         self.weaponmodel = "progs/v_rock.mdl";
  867.         self.weaponframe = 0;
  868.         self.items = self.items | IT_ROCKETS;
  869.     }
  870.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  871.     {
  872.         self.currentammo = self.ammo_rockets;
  873.         self.weaponmodel = "progs/v_rock2.mdl";
  874.         self.weaponframe = 0;
  875.         self.items = self.items | IT_ROCKETS;
  876.     }
  877.     else if (self.weapon == IT_LIGHTNING)
  878.     {
  879.         self.currentammo = self.ammo_cells;
  880.         self.weaponmodel = "progs/v_light.mdl";
  881.         self.weaponframe = 0;
  882.         self.items = self.items | IT_CELLS;
  883.     }
  884.     else
  885.     {
  886.         self.currentammo = 0;
  887.         self.weaponmodel = "";
  888.         self.weaponframe = 0;
  889.     }
  890. };
  891.  
  892. float() W_BestWeapon =
  893. {
  894.     local   float   it;
  895.     
  896.     it = self.items;
  897.  
  898.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  899.         return IT_LIGHTNING;
  900.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  901.         return IT_SUPER_NAILGUN;
  902.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  903.         return IT_SUPER_SHOTGUN;
  904.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  905.         return IT_NAILGUN;
  906.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  907.         return IT_SHOTGUN;
  908.         
  909. /*
  910.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  911.         return IT_ROCKET_LAUNCHER;
  912.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  913.         return IT_GRENADE_LAUNCHER;
  914.  
  915. */
  916.  
  917.     return IT_AXE;
  918. };
  919.  
  920. float() W_CheckNoAmmo =
  921. {
  922.     if (self.currentammo > 0)
  923.         return TRUE;
  924.  
  925.     if (self.weapon == IT_AXE)
  926.         return TRUE;
  927.     
  928.     self.weapon = W_BestWeapon ();
  929.  
  930.     W_SetCurrentAmmo ();
  931.     
  932. // drop the weapon down
  933.     return FALSE;
  934. };
  935.  
  936. /*
  937. ============
  938. W_Attack
  939.  
  940. An attack impulse can be triggered now
  941. ============
  942. */
  943. void()  player_axe1;
  944. void()  player_axeb1;
  945. void()  player_axec1;
  946. void()  player_axed1;
  947. void()  player_shot1;
  948. void()  player_nail1;
  949. void()  player_light1;
  950. void()  player_rocket1;
  951.  
  952. void() W_Attack =
  953. {
  954.     local   float   r;
  955.  
  956.     if (!W_CheckNoAmmo ())
  957.         return;
  958.  
  959.     makevectors     (self.v_angle);                 // calculate forward angle for velocity
  960.     self.show_hostile = time + 1;   // wake monsters up
  961.  
  962.     if (self.weapon == IT_AXE)
  963.     {
  964.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  965.         r = random();
  966.         if (r < 0.25)
  967.             player_axe1 ();
  968.         else if (r<0.5)
  969.             player_axeb1 ();
  970.         else if (r<0.75)
  971.             player_axec1 ();
  972.         else
  973.             player_axed1 ();
  974.         self.attack_finished = time + 0.5;
  975.     }
  976.     else if (self.weapon == IT_SHOTGUN)
  977.     {
  978.         player_shot1 ();
  979.         W_FireShotgun ();
  980.         self.attack_finished = time + 0.5;
  981.     }
  982.     else if (self.weapon == IT_SUPER_SHOTGUN)
  983.     {
  984.         player_shot1 ();
  985.         W_FireSuperShotgun ();
  986.         self.attack_finished = time + 0.7;
  987.     }
  988.     else if (self.weapon == IT_NAILGUN)
  989.     {
  990.         player_nail1 ();
  991.     }
  992.     else if (self.weapon == IT_SUPER_NAILGUN)
  993.     {
  994.         player_nail1 ();
  995.     }
  996.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  997.     {
  998.         player_rocket1();
  999.         W_FireGrenade();
  1000.         self.attack_finished = time + 0.6;
  1001.     }
  1002.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1003.     {
  1004.         player_rocket1();
  1005.         W_FireRocket();
  1006.         self.attack_finished = time + 0.8;
  1007.     }
  1008.     else if (self.weapon == IT_LIGHTNING)
  1009.     {
  1010.         player_light1();
  1011.         self.attack_finished = time + 0.1;
  1012.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1013.     }
  1014. };
  1015.  
  1016. /*
  1017. ============
  1018. W_ChangeWeapon
  1019.  
  1020. ============
  1021. */
  1022. void() W_ChangeWeapon =
  1023. {
  1024.     local   float   it, am, fl;
  1025.     
  1026.     it = self.items;
  1027.     am = 0;
  1028.     
  1029.     if (self.impulse == 1)
  1030.     {
  1031.         fl = IT_AXE;
  1032.     }
  1033.     else if (self.impulse == 2)
  1034.     {
  1035.         fl = IT_SHOTGUN;
  1036.         if (self.ammo_shells < 1)
  1037.             am = 1;
  1038.     }
  1039.     else if (self.impulse == 3)
  1040.     {
  1041.         fl = IT_SUPER_SHOTGUN;
  1042.         if (self.ammo_shells < 2)
  1043.             am = 1;
  1044.     }               
  1045.     else if (self.impulse == 4)
  1046.     {
  1047.         fl = IT_NAILGUN;
  1048.         if (self.ammo_nails < 1)
  1049.             am = 1;
  1050.     }
  1051.     else if (self.impulse == 5)
  1052.     {
  1053.         fl = IT_SUPER_NAILGUN;
  1054.         if (self.ammo_nails < 2)
  1055.             am = 1;
  1056.     }
  1057.     else if (self.impulse == 6)
  1058.     {
  1059.         fl = IT_GRENADE_LAUNCHER;
  1060.         if (self.ammo_rockets < 1)
  1061.             am = 1;
  1062.     }
  1063.     else if (self.impulse == 7)
  1064.     {
  1065.         fl = IT_ROCKET_LAUNCHER;
  1066.         if (self.ammo_rockets < 1)
  1067.             am = 1;
  1068.     }
  1069.     else if (self.impulse == 8)
  1070.     {
  1071.         fl = IT_LIGHTNING;
  1072.         if (self.ammo_cells < 1)
  1073.             am = 1;
  1074.     }
  1075.  
  1076.     self.impulse = 0;
  1077.     
  1078.     if (!(self.items & fl))
  1079.     {       // don't have the weapon or the ammo
  1080.         sprint (self, "no weapon.\n");
  1081.         return;
  1082.     }
  1083.     
  1084.     if (am)
  1085.     {       // don't have the ammo
  1086.         sprint (self, "not enough ammo.\n");
  1087.         return;
  1088.     }
  1089.  
  1090. //
  1091. // set weapon, set ammo
  1092. //
  1093.     self.weapon = fl;               
  1094.     W_SetCurrentAmmo ();
  1095. };
  1096.  
  1097. /*
  1098. ============
  1099. CheatCommand
  1100. ============
  1101. */
  1102. void() CheatCommand =
  1103. {
  1104.     if (deathmatch || coop)
  1105.         return;
  1106.  
  1107.     self.ammo_rockets = 100;
  1108.     self.ammo_nails = 200;
  1109.     self.ammo_shells = 100;
  1110.     self.items = self.items | 
  1111.         IT_AXE |
  1112.         IT_SHOTGUN |
  1113.         IT_SUPER_SHOTGUN |
  1114.         IT_NAILGUN |
  1115.         IT_SUPER_NAILGUN |
  1116.         IT_GRENADE_LAUNCHER |
  1117.         IT_ROCKET_LAUNCHER |
  1118.         IT_KEY1 | IT_KEY2;
  1119.  
  1120.     self.ammo_cells = 200;
  1121.     self.items = self.items | IT_LIGHTNING;
  1122.  
  1123.     self.weapon = IT_ROCKET_LAUNCHER;
  1124.     self.impulse = 0;
  1125.     W_SetCurrentAmmo ();
  1126. };
  1127.  
  1128. /*
  1129. ============
  1130. CycleWeaponCommand
  1131.  
  1132. Go to the next weapon with ammo
  1133. ============
  1134. */
  1135. void() CycleWeaponCommand =
  1136. {
  1137.     local   float   it, am;
  1138.     
  1139.     it = self.items;
  1140.     self.impulse = 0;
  1141.     
  1142.     while (1)
  1143.     {
  1144.         am = 0;
  1145.  
  1146.         if (self.weapon == IT_LIGHTNING)
  1147.         {
  1148.             self.weapon = IT_AXE;
  1149.         }
  1150.         else if (self.weapon == IT_AXE)
  1151.         {
  1152.             self.weapon = IT_SHOTGUN;
  1153.             if (self.ammo_shells < 1)
  1154.                 am = 1;
  1155.         }
  1156.         else if (self.weapon == IT_SHOTGUN)
  1157.         {
  1158.             self.weapon = IT_SUPER_SHOTGUN;
  1159.             if (self.ammo_shells < 2)
  1160.                 am = 1;
  1161.         }               
  1162.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1163.         {
  1164.             self.weapon = IT_NAILGUN;
  1165.             if (self.ammo_nails < 1)
  1166.                 am = 1;
  1167.         }
  1168.         else if (self.weapon == IT_NAILGUN)
  1169.         {
  1170.             self.weapon = IT_SUPER_NAILGUN;
  1171.             if (self.ammo_nails < 2)
  1172.                 am = 1;
  1173.         }
  1174.         else if (self.weapon == IT_SUPER_NAILGUN)
  1175.         {
  1176.             self.weapon = IT_GRENADE_LAUNCHER;
  1177.             if (self.ammo_rockets < 1)
  1178.                 am = 1;
  1179.         }
  1180.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1181.         {
  1182.             self.weapon = IT_ROCKET_LAUNCHER;
  1183.             if (self.ammo_rockets < 1)
  1184.                 am = 1;
  1185.         }
  1186.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1187.         {
  1188.             self.weapon = IT_LIGHTNING;
  1189.             if (self.ammo_cells < 1)
  1190.                 am = 1;
  1191.         }
  1192.     
  1193.         if ( (self.items & self.weapon) && am == 0)
  1194.         {
  1195.             W_SetCurrentAmmo ();
  1196.             return;
  1197.         }
  1198.     }
  1199.  
  1200. };
  1201.  
  1202. /*
  1203. ============
  1204. ServerflagsCommand
  1205.  
  1206. Just for development
  1207. ============
  1208. */
  1209. void() ServerflagsCommand =
  1210. {
  1211.     serverflags = serverflags * 2 + 1;
  1212. };
  1213.  
  1214. void() QuadCheat =
  1215. {
  1216.     if (deathmatch || coop)
  1217.         return;
  1218.     self.super_time = 1;
  1219.     self.super_damage_finished = time + 30;
  1220.     self.items = self.items | IT_QUAD;
  1221.     dprint ("quad cheat\n");
  1222. };
  1223.  
  1224. /*
  1225. ============
  1226. ImpulseCommands
  1227.  
  1228. ============
  1229. */
  1230. void() ImpulseCommands =
  1231. {
  1232.     if (self.impulse >= 1 && self.impulse <= 8)
  1233.         W_ChangeWeapon ();
  1234.  
  1235.     if (self.impulse == 9)
  1236.         CheatCommand ();
  1237.     if (self.impulse == 10)
  1238.         CycleWeaponCommand ();
  1239.     if (self.impulse == 11)
  1240.         ServerflagsCommand ();
  1241.  
  1242. // *******************QTalk impulse commands******************************        
  1243.     
  1244.     if ((self.impulse == 49) || (self.impulse == 50) || (self.impulse == 51))
  1245.     {
  1246.         if (self.impulse == 49)
  1247.         play_abuse ();
  1248.         else if (self.impulse == 50)
  1249.         play_prekill ();
  1250.         else if (self.impulse == 51)
  1251.         play_letsgo ();
  1252.     }
  1253.  
  1254. // *********************************************************************
  1255.     if (self.impulse == 255)
  1256.         QuadCheat ();
  1257.         
  1258.     self.impulse = 0;
  1259. };
  1260.  
  1261. /*
  1262. ============
  1263. W_WeaponFrame
  1264.  
  1265. Called every frame so impulse events can be handled as well as possible
  1266. ============
  1267. */
  1268. void() W_WeaponFrame =
  1269. {
  1270.     if (time < self.attack_finished)
  1271.         return;
  1272.  
  1273.     ImpulseCommands ();
  1274.     
  1275. // check for attack
  1276.     if (self.button0)
  1277.     {
  1278.         SuperDamageSound ();
  1279.         W_Attack ();
  1280.     }
  1281. };
  1282.  
  1283. /*
  1284. ========
  1285. SuperDamageSound
  1286.  
  1287. Plays sound if needed
  1288. ========
  1289. */
  1290. void() SuperDamageSound =
  1291. {
  1292.     if (self.super_damage_finished > time)
  1293.     {
  1294.         if (self.super_sound < time)
  1295.         {
  1296.             self.super_sound = time + 1;
  1297.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1298.         }
  1299.     }
  1300.     return;
  1301. };
  1302.  
  1303.  
  1304.